import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xiaolong
 * @version 1.0
 * @description: TODO
 * @date 2022/2/18 20:18
 */

@Slf4j
public class testController {

    @Autowired
    private SynchronizedByKey synchronizedByKey;

    /**
     * @description: 同步锁 （实现锁住同一个订单，不同订单可以并行）
     * @param
     * @return
     */
    @ResponseBody
    @GetMapping("/process/{orderId}")
    public void process(@PathVariable("orderId") String orderId ){
        //如果这里是this的话，说明整个方法体都只能一个线程进入，
        // 当是如果我们锁的是订单号不加intern()，说明我们锁的是orderId这个对象，并不是这个的值，
        // 故我们intern（）加了这个方法后说明我们将这个值加入到了常量池中，当下次进来的orderId会去常量池中去找到相同的值
        synchronized (orderId.intern()){
            log.debug("[{}]开始",orderId);
            //中间业务
            log.debug("[{}] 结束",orderId);
        }
    }



    //第二种方式的同步锁，常用！！！
    Map<String,Object> mutexCache = new HashMap<>();

    @ResponseBody
    @GetMapping("/process/{orderId}")
    public void process1(@PathVariable("orderId") String orderId ){
        Object mutex4Key;
        synchronized (this){
            mutex4Key = mutexCache.get(orderId);
            if (mutex4Key ==null){
                mutex4Key = new Object();
                mutexCache.put(orderId,mutex4Key);
            }
        }

        synchronized (mutex4Key){
            log.debug("[{}]开始",orderId);
            //中间业务
            log.debug("[{}] 结束",orderId);
            mutexCache.remove(orderId);
        }
    }


   //线程安全
    Map<String,Object> mutexCache1 = new ConcurrentHashMap<>();
    @ResponseBody
    @GetMapping("/process/{orderId}")
    public void process2(@PathVariable("orderId") String orderId ){

        //如果 key 对应的 value 不存在，则使用获取 remappingFunction 重新计算后的值，并保存为该 key 的 value，否则返回 value。
        Object mutex4Key = mutexCache1.computeIfAbsent(orderId, k -> new Object());

        synchronized (mutex4Key){
            log.debug("[{}]开始",orderId);
            //中间业务
            log.debug("[{}] 结束",orderId);
            mutexCache1.remove(orderId);
        }


        synchronizedByKey.exec(orderId,()->{
            log.debug("[{}]开始",orderId);
            //中间业务
            log.debug("[{}] 结束",orderId);
        });

    }


    public static void main(String[] args) {

    }


}
